package com.engr.lyx.starter;

import com.engr.lyx.common.annotation.CurrentUser;
import com.engr.lyx.common.config.SwaggerProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.OAuthBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import springfox.documentation.swagger2.configuration.Swagger2DocumentationConfiguration;

import java.util.Arrays;
import java.util.Collections;

/**
 * @author : LiuYanXin
 * @Description : swagger 自动装配
 * @date : 2019-04-25 16:25
 */
@Configuration
@ConditionalOnProperty(prefix = "blog.swagger", name = "enable", havingValue = "true")
@EnableSwagger2
@EnableConfigurationProperties({SwaggerProperties.class})
@Import({Swagger2DocumentationConfiguration.class})
public class SwaggerAutoConfig {

    @Autowired
    private SwaggerProperties swaggerProperties;

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors
                        .withClassAnnotation(RestController.class))
                .paths(PathSelectors.any()).build()
                .securitySchemes(Collections.singletonList(securityScheme()))
                .securityContexts(Collections.singletonList(securityContext()))
                .ignoredParameterTypes(CurrentUser.class);
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title(swaggerProperties.getTitle())
                .description(swaggerProperties.getDescription())
                .termsOfServiceUrl(
                        swaggerProperties.getTermsOfServiceUrl())
                .contact(
                        new Contact(
                                swaggerProperties.getAuthor(),
                                swaggerProperties.getGiteeUrl(),
                                swaggerProperties.getEmail())).version(swaggerProperties.getVersion()).build();
    }

    /**
     * 设置Oauth2的认证模式。这里使用密码模式
     *
     * @return
     */
    private SecurityScheme securityScheme() {
        GrantType grantType = new ResourceOwnerPasswordCredentialsGrant("http://localhost:8080/auth" + "/oauth/token");

        return new OAuthBuilder()
                .name("blog_OAuth")
                .grantTypes(Collections.singletonList(grantType))
                .scopes(Arrays.asList(scopes()))
                .build();
    }

    /**
     * 这里设置 swagger2 认证的安全上下文
     */
    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(Collections.singletonList(new SecurityReference("blog_OAuth", scopes())))
                .forPaths(PathSelectors.any())
                .build();
    }

    /**
     * 应用允许认证的scope
     */
    private AuthorizationScope[] scopes() {
        return new AuthorizationScope[]{
                new AuthorizationScope("server", "blog-app scope!")
        };
    }

}
